www.gusucode.com > VC 2D游戏编辑器-源码程序 > VC 2D游戏编辑器-源码程序/code/game_Source/GameLib/findpathA.cpp
//Download by http://www.NewXing.com #include "globle.h" #include "globle_func.h" #include "..\\newgame.h" #include "findpathA.h" #define MAXINT 32767 FINDPATH_A8::FINDPATH_A8( ) { sort_queue = NULL; store_queue = NULL; pLink = NULL; dis_map = NULL; path1_X = NULL; path1_Y = NULL; bBeginDir = false; IsFound = false; memset(pathX, -1, TABLE_X*TABLE_Y*sizeof(int)); memset(pathY, -1, TABLE_X*TABLE_Y*sizeof(int)); } void FINDPATH_A8::find(long StartX, long StartY, long EndX, long EndY) { IsFound = false; level = 0; if(sort_queue) { while(sort_queue) { pLink = sort_queue; sort_queue = sort_queue->Next; P_SAFE_DELETE(pLink); } sort_queue= NULL; } if(store_queue) { while(store_queue) { pLink = store_queue; store_queue = store_queue->Next; P_SAFE_DELETE(pLink); } store_queue= NULL; } start_x = lStartX = StartX/32; start_y = lStartY = StartY/32; end_x = lEndX = EndX/32; end_y = lEndY = EndY/32; memset(pathX, -1, TABLE_X*TABLE_Y*sizeof(int)); memset(pathY, -1, TABLE_X*TABLE_Y*sizeof(int)); level = 0; if((start_x == end_x)&&(start_y == end_y)) { return; } int nx, ny ,i; path1_X = pathX; path1_Y = pathY; do { nx = abs(end_x - lStartX); ny = abs(end_y - lStartY); if(nx > 32) if(end_x > start_x) lEndX = lStartX + 32; else lEndX = lStartX - 32; if(ny > 32) if(end_y > start_y) lEndY = lStartY + 32; else lEndY = lStartY - 32; FindWay( ); if(IsFound == false) { IsFound = false; long lNearX, lNearY, lR; bool IsFindNear = false; lR = 0; while(!IsFindNear) { lR ++; for(i = 0; i < 360; i +=1) { lNearX = (long)(lR*cos_O[i]) + lEndX; lNearY = (long)(lR*sin_O[i]) + lEndY; if(lNearX < 0) lNearX = 0; if(lNearY < 0) lNearY = 0; if(lNearX > Map->pHeader.nWidth-1) lNearX = Map->pHeader.nWidth-1; if(lNearY > Map->pHeader.nHeight-1) lNearY = Map->pHeader.nHeight-1; if(dis_map[lNearY-iPageStartY][lNearX-iPageStartX] != 0xffffffff) { IsFindNear = true; break; } } } lEndX = lNearX; lEndY = lNearY; FindWay( ); } lStartX = lEndX; lStartY = lEndY; }while((nx > 32)||(ny > 32)); end_x = lEndX; end_y = lEndY; pLink = NULL; if(dis_map) { PA_SAFE_DELETE(dis_map); } } void FINDPATH_A8::init_queue() { sort_queue = new LINK; sort_queue->node = NULL; sort_queue->f = -1; sort_queue->Next = new LINK; sort_queue->Next->node = NULL; sort_queue->Next->f = MAXINT; sort_queue->Next->Next = NULL; store_queue = new LINK; store_queue->node = NULL; store_queue->f = -1; store_queue->Next = NULL; } void FINDPATH_A8::enter_queue(TREE * node,int f) { LINK * p = sort_queue; LINK * father, * q; while((f > p->f) &&(p != NULL)) { father=p; p=p->Next; } q= new LINK; q->f = f; q->node = node; q->Next = p; father->Next = q; } TREE * FINDPATH_A8::get_from_queue() { LINK * bestchoice = sort_queue->Next; LINK * next = sort_queue->Next->Next; sort_queue->Next = next; bestchoice->Next = store_queue->Next; store_queue->Next = bestchoice; return bestchoice->node; } int FINDPATH_A8::trytile(int x,int y,TREE * father) { TREE * p=father; unsigned int h; if(Map->pSurfaceData[y*Map->pHeader.nWidth+x].nPass == 0) return 1; // 如果 (x,y) 处是障碍,失败 if((x >= iPageStartX + TABLE_X)||(y >= iPageStartY + TABLE_Y)||(x < iPageStartX)||(y < iPageStartY)) return 1; //如果越界,失败 if((x >= Map->pHeader.nWidth)||(x < 0)||(y >= Map->pHeader.nWidth)||(y < 0)) return 1; h = father->h+1; if (h >= dis_map[y-iPageStartY][x-iPageStartX]) return 1; // 如果曾经有更好的方案移动到 (x,y) 失败 dis_map[y-iPageStartY][x-iPageStartX] = h; // 记录这次到 (x,y) 的距离为历史最佳距离 // 将这步方案记入待处理队列 p = new TREE; p->father = father; p->h = father->h+1; p->x = x; p->y = y; enter_queue(p,p->h + judge(x, y)); return 0; } void FINDPATH_A8::pop_stack() { LINK * s = store_queue->Next; if(s != NULL) { store_queue->Next = store_queue->Next->Next; P_SAFE_DELETE(s->node); P_SAFE_DELETE(s); } } void FINDPATH_A8::freetree() { LINK * p; if(store_queue) while(store_queue) { p=store_queue; P_SAFE_DELETE(p->node); store_queue=store_queue->Next; P_SAFE_DELETE(p); } if(sort_queue) while (sort_queue) { p=sort_queue; P_SAFE_DELETE(p->node); sort_queue=sort_queue->Next; P_SAFE_DELETE(p); } } int FINDPATH_A8::judge(int x, int y) { int distance; distance=abs(lEndX-x)+abs(lEndY-y); return distance; } void FINDPATH_A8::FindWay( ) { TREE * root; int i; if(dis_map) PA_SAFE_DELETE(dis_map); dis_map = (unsigned int **)new unsigned int[TABLE_Y]; for(i = 0; i < TABLE_Y; i++) { dis_map[i] = new unsigned int[TABLE_X]; memset(dis_map[i],0xff,TABLE_X*sizeof(unsigned int)); //填充dis_map为0XFF,表示各点未曾经过 } init_queue(); iPageStartX = (lStartX+lEndX-TABLE_X)>>1; iPageStartY = (lStartY+lEndY-TABLE_Y)>>1; root = new TREE; root->x = lStartX; root->y = lStartY; root->h = 0; root->father = NULL; enter_queue(root,judge(lStartX,lStartY)); for (;;) { int child, x, y; root=get_from_queue(); if (root==NULL) { return; } x = root->x; y = root->y; if (x == lEndX && y == lEndY) break; // 达到目的地成功返回 child=trytile(x,y-1,root); //尝试向上移动 child&=trytile(x,y+1,root); //尝试向下移动 child&=trytile(x-1,y,root); //尝试向左移动 child&=trytile(x+1,y,root); //尝试向右移动 child&=trytile(x+1,y-1,root); //尝试向右上移动 child&=trytile(x+1,y+1,root); //尝试向右下移动 child&=trytile(x-1,y+1,root); //尝试向左下移动 child&=trytile(x-1,y-1,root); //尝试向左上移动 if (child!=0) pop_stack(); // 如果四个方向均不能移动,释放这个死节点 } // 回溯树,将求出的最佳路径保存在 path[] 中 for (i=0; root; i++) { path1_X[i] = (root->x)<<5; path1_Y[i] = (root->y)<<5; root=root->father; level++; } level -= 2; path1_X += i; path1_Y += i; freetree(); root = NULL; IsFound = true; } //************************************************************************************// FINDPATH_A4::FINDPATH_A4( ) { sort_queue = NULL; store_queue = NULL; pLink = NULL; dis_map = NULL; path1_X = NULL; path1_Y = NULL; bBeginDir = false; IsFound = false; memset(pathX, -1, TABLE_X*TABLE_Y*sizeof(int)); memset(pathY, -1, TABLE_X*TABLE_Y*sizeof(int)); } void FINDPATH_A4::find(long StartX, long StartY, long EndX, long EndY) { IsFound = false; level = 0; if(sort_queue) { while(sort_queue) { pLink = sort_queue; sort_queue = sort_queue->Next; P_SAFE_DELETE(pLink); } sort_queue= NULL; } if(store_queue) { while(store_queue) { pLink = store_queue; store_queue = store_queue->Next; P_SAFE_DELETE(pLink); } store_queue= NULL; } start_x = lStartX = StartX/32; start_y = lStartY = StartY/32; end_x = lEndX = EndX/32; end_y = lEndY = EndY/32; memset(pathX, -1, TABLE_X*TABLE_Y*sizeof(int)); memset(pathY, -1, TABLE_X*TABLE_Y*sizeof(int)); if((start_x == end_x)&&(start_y == end_y)) { return; } int nx, ny ,i; path1_X = pathX; path1_Y = pathY; do { nx = abs(end_x - lStartX); ny = abs(end_y - lStartY); if(nx > 32) if(end_x > start_x) lEndX = lStartX + 32; else lEndX = lStartX - 32; if(ny > 32) if(end_y > start_y) lEndY = lStartY + 32; else lEndY = lStartY - 32; FindWay( ); if(IsFound == false) { IsFound = false; long lNearX, lNearY, lR; bool IsFindNear = false; lR = 0; while(!IsFindNear) { lR ++; for(i = 0; i < 360; i +=1) { lNearX = (long)(lR*cos_O[i]) + lEndX; lNearY = (long)(lR*sin_O[i]) + lEndY; if(lNearX < 0) lNearX = 0; if(lNearY < 0) lNearY = 0; if(lNearX > Map->pHeader.nWidth-1) lNearX = Map->pHeader.nWidth-1; if(lNearY > Map->pHeader.nHeight-1) lNearY = Map->pHeader.nHeight-1; if(dis_map[lNearY-iPageStartY][lNearX-iPageStartX] != 0xffffffff) { IsFindNear = true; break; } } } lEndX = lNearX; lEndY = lNearY; FindWay( ); } lStartX = lEndX; lStartY = lEndY; }while((nx > 32)||(ny > 32)); end_x = lEndX; end_y = lEndY; pLink = NULL; if(dis_map) { PA_SAFE_DELETE(dis_map); } } void FINDPATH_A4::init_queue() { sort_queue = new LINK; sort_queue->node = NULL; sort_queue->f = -1; sort_queue->Next = new LINK; sort_queue->Next->node = NULL; sort_queue->Next->f = MAXINT; sort_queue->Next->Next = NULL; store_queue = new LINK; store_queue->node = NULL; store_queue->f = -1; store_queue->Next = NULL; } void FINDPATH_A4::enter_queue(TREE * node,int f) { LINK * p = sort_queue; LINK * father, * q; while((f > p->f) &&(p != NULL)) { father=p; p=p->Next; } q= new LINK; q->f = f; q->node = node; q->Next = p; father->Next = q; } TREE * FINDPATH_A4::get_from_queue() { LINK * bestchoice = sort_queue->Next; LINK * next = sort_queue->Next->Next; sort_queue->Next = next; bestchoice->Next = store_queue->Next; store_queue->Next = bestchoice; return bestchoice->node; } int FINDPATH_A4::trytile(int x,int y,TREE * father) { TREE * p=father; unsigned int h; if(Map->pSurfaceData[y*Map->pHeader.nWidth+x].nPass == 0) return 1; // 如果 (x,y) 处是障碍,失败 if((x >= iPageStartX + TABLE_X)||(y >= iPageStartY + TABLE_Y)||(x < iPageStartX)||(y < iPageStartY)) return 1; //如果越界,失败 if((x >= Map->pHeader.nWidth)||(x < 0)||(y >= Map->pHeader.nWidth)||(y < 0)) return 1; h = father->h+1; if (h >= dis_map[y-iPageStartY][x-iPageStartX]) return 1; // 如果曾经有更好的方案移动到 (x,y) 失败 dis_map[y-iPageStartY][x-iPageStartX] = h; // 记录这次到 (x,y) 的距离为历史最佳距离 // 将这步方案记入待处理队列 p = new TREE; p->father = father; p->h = father->h+1; p->x = x; p->y = y; enter_queue(p,p->h + judge(x, y)); return 0; } void FINDPATH_A4::pop_stack() { LINK * s = store_queue->Next; if(s != NULL) { store_queue->Next = store_queue->Next->Next; P_SAFE_DELETE(s->node); P_SAFE_DELETE(s); } } void FINDPATH_A4::freetree() { LINK * p; if(store_queue) while(store_queue) { p=store_queue; P_SAFE_DELETE(p->node); store_queue=store_queue->Next; P_SAFE_DELETE(p); } if(sort_queue) while (sort_queue) { p=sort_queue; P_SAFE_DELETE(p->node); sort_queue=sort_queue->Next; P_SAFE_DELETE(p); } } int FINDPATH_A4::judge(int x, int y) { int distance; distance=abs(lEndX-x)+abs(lEndY-y); return distance; } void FINDPATH_A4::FindWay( ) { TREE * root; int i; if(dis_map) PA_SAFE_DELETE(dis_map); dis_map = (unsigned int **)new unsigned int[TABLE_Y]; for(i = 0; i < TABLE_Y; i++) { dis_map[i] = new unsigned int[TABLE_X]; memset(dis_map[i],0xff,TABLE_X*sizeof(unsigned int)); //填充dis_map为0XFF,表示各点未曾经过 } init_queue(); iPageStartX = (lStartX+lEndX-TABLE_X)>>1; iPageStartY = (lStartY+lEndY-TABLE_Y)>>1; root = new TREE; root->x = lStartX; root->y = lStartY; root->h = 0; root->father = NULL; enter_queue(root,judge(lStartX,lStartY)); for (;;) { int child, x, y; root=get_from_queue(); if (root==NULL) { return; } x = root->x; y = root->y; if (x == lEndX && y == lEndY) break; // 达到目的地成功返回 child=trytile(x,y-1,root); //尝试向上移动 child&=trytile(x,y+1,root); //尝试向下移动 child&=trytile(x-1,y,root); //尝试向左移动 child&=trytile(x+1,y,root); //尝试向右移动 // child&=trytile(x+1,y-1,root); //尝试向右上移动 // child&=trytile(x+1,y+1,root); //尝试向右下移动 // child&=trytile(x-1,y+1,root); //尝试向左下移动 // child&=trytile(x-1,y-1,root); //尝试向左上移动 if (child!=0) pop_stack(); // 如果四个方向均不能移动,释放这个死节点 } // 回溯树,将求出的最佳路径保存在 path[] 中 for (i=0; root; i++) { path1_X[i] = (root->x)<<5; path1_Y[i] = (root->y)<<5; root=root->father; level++; } level -= 2; path1_X += i; path1_Y += i; freetree(); root = NULL; IsFound = true; }